import { compose } from "./compose";

/**
 * 中间件实现
 * ! 核心思想就是保留之前 dispatch，覆盖之前方法并在里面调用之前保存下来方法(也就是组合一个大的 dipacth) 类似切片
 * @param  {...any} middlewares 每个中间件函数
 * @returns 
 */
export function applyMiddleware(...middlewares) {
    return (createStore) => (...args) => {
        // args 为 createStore 方法中的形参也就包含 reducer 和 defaultState
        const store = createStore(...args); // 创建仓库
        // 重写 dispatch 函数
        let dispatch = () => {
            throw new Error(
                'Dispatching while constructing your middleware is not allowed. ' +
                'Other middleware would not be applied to this dispatch.'
            )
        }
        // 取原 store 中部分方法
        const middlewareAPI = {
            getState: store.getState,
            dispatch: (...args) => dispatch(...args),
        }
        // 遍历中间件将切取的 store 中部分方法传入作为参数 
        const chain = middlewares.map((middleware) => middleware(middlewareAPI));
        //? 此方法中难点理解(通过 compose 函数组合成大的 dispatch )
        dispatch = compose(...chain)(store.dispatch);
        return {
            ...store,
            dispatch, // 覆盖 store 中 dispatch 方法
        }
    }
}
